/*
* Copyright 2013, The Sporting Exchange Limited
* Copyright 2014, Simon Matić Langford
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.betfair.testing.utils.cougar.helpers;
import com.betfair.testing.utils.cougar.beans.BatchedRequestBean;
import com.betfair.testing.utils.cougar.beans.HttpCallBean;
import com.betfair.testing.utils.cougar.beans.HttpResponseBean;
import com.betfair.testing.utils.cougar.daos.CougarDefaultDAO;
import com.betfair.testing.utils.cougar.daos.ICougarDAO;
import com.betfair.testing.utils.cougar.enums.CougarMessageContentTypeEnum;
import com.betfair.testing.utils.cougar.enums.CougarMessageProtocolRequestTypeEnum;
import com.betfair.testing.utils.cougar.misc.IReflect;
import com.betfair.testing.utils.cougar.misc.Reflect;
import com.betfair.testing.utils.cougar.misc.XMLHelpers;
import com.sun.tools.attach.AgentInitializationException;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.xerces.dom.DocumentImpl;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.TabularData;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.MimeHeader;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CougarHelpers {
private static final Logger logger = LoggerFactory.getLogger(CougarHelpers.class);
private ICougarDAO cougarDAO = new CougarDefaultDAO();
private IReflect reflect = new Reflect();
private static final String CONNECTOR_ADDRESS = "com.sun.management.jmxremote.localConnectorAddress";
private static final String SOAP_CALL_TEXT = "Make Cougar SOAP Call : ";
private static final String JMX_SETTING_ERROR = "Problem setting JMX attribute: ";
private static final String JMX_RETRIEVAL_ERROR = "Problem retrieving JMX attribute value: ";
private static final String JMX_INVOKE_ERROR = "Problem invoking JMX operation: ";
private static final String JSON_CONTENT = "application/json";
private static final String XML_CONTENT = "application/xml";
private static final String UTF8 = "utf-8";
// Map of operation names to paths (where different)
// TODO Would be better to generate this automatically
private static final Map<String, String> OPERATION_PATHS = new HashMap<String, String>(){
{
put("testSimpleMapGet","simpleMapGet");
put("testSimpleListGet","simpleListGet");
put("testSimpleSetGet","simpleSetGet");
put("testSimpleGet","simple");
put("testSimpleCacheGet","cache");
put("testLargeGet","largeGet");
put("testLargeMapGet","map");
put("testMapsNameClash","map1");
put("testGetTimeout","simple/timeout");
put("testParameterStyles","styles");
put("testDateRetrieval","dates");
put("testDoubleHandling","doubles");
put("testListRetrieval","primitiveLists");
put("testComplexMutator","complex");
put("testLargePost","largePost");
put("testException","exception");
put("testSecureService","secure");
put("testSimpleTypeReplacement","simpletypes");
put("testStringableLists","simpleLists");
put("testBodyParams","multibody");
put("testNoParams","noparams");
put("testDirectMapReturn","direct/map");
put("testDirectListReturn","direct/list");
put("boolSimpleTypeEcho","boolEcho");
put("byteSimpleTypeEcho","byteEcho");
put("i32SimpleTypeEcho","i32Echo");
put("i64SimpleTypeEcho","i64Echo");
put("floatSimpleTypeEcho","floatEcho");
put("doubleSimpleTypeEcho","doubleEcho");
put("stringSimpleTypeEcho","stringEcho");
put("dateTimeSimpleTypeEcho","dateTimeEcho");
put("i32ListSimpleTypeEcho","i32ListEcho");
put("i32SetSimpleTypeEcho","i32SetEcho");
put("i32MapSimpleTypeEcho","i32MapEcho");
put("testIdentityChain","identityChain");
put("getDetailedHealthStatus","detailed");
put("isHealthy","summary");
}
};
private JMXConnector jmxc = null;
/*
* Send a request to a locally running Cougar container via SOAP as per the
* passed parameters.
*
* @param message
* @param serviceName
* @param version
* @param httpBean
* @return
*/
public HttpResponseBean makeCougarSOAPCall(SOAPMessage message,
String serviceName, String version, HttpCallBean httpBean) {
try {
//Debugging code
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
message.writeTo(outStream);
SOAPConnectionFactory connectionFactory = SOAPConnectionFactory
.newInstance();
SOAPConnection connection = connectionFactory.createConnection();
// this can either be a SOAPException or SOAPMessage
HttpResponseBean responseBean = new HttpResponseBean();
Object response;
String host = httpBean.getHost();
String port = httpBean.getPort();
String endPoint = "http://" + host + ":" + port + "/" + serviceName + "Service/" + version;
try {
response = connection.call(message, endPoint);
} catch (SOAPException e) {
response = e;
} finally {
connection.close();
}
responseBean.setResponseObject(handleResponse(response, responseBean));
return responseBean;
} catch (SOAPException | IOException | ParserConfigurationException | TransformerException e) {
throw new RuntimeException(SOAP_CALL_TEXT + e, e);
}
}
/*
* Handle the response of the SOAP call
*
* @param response
* @return
* @throws SOAPException
* @throws IOException
* @throws ParserConfigurationException
* @throws TransformerException
*/
private Object handleResponse(Object response, HttpResponseBean responseBean) throws SOAPException,
IOException, ParserConfigurationException, TransformerException {
Class<?> clazz = response.getClass();
if (clazz
.getName()
.equalsIgnoreCase(
"com.sun.xml.internal.messaging.saaj.soap.ver1_1.Message1_1Impl")
|| clazz
.getName()
.equalsIgnoreCase(
"com.sun.xml.messaging.saaj.soap.ver1_1.Message1_1Impl")) {
return handleSoapResponse((SOAPMessage) response, responseBean);
}
else{ // else assume that an exception has been thrown
return response;
}
}
/*
* ???
*
* @param response
* @param responseBean
* @throws DOMException
* @throws SOAPException
*/
private void extractHeaderDataSOAP(SOAPMessage response, HttpResponseBean responseBean) throws SOAPException
{
//extract MimeHeaders
MimeHeaders mime = response.getMimeHeaders();
Iterator<MimeHeader> iter = mime.getAllHeaders();
while(iter.hasNext())
{
MimeHeader mimeH = iter.next();
responseBean.addEntryToResponseHeaders(mimeH.getName(),mimeH.getValue());
}
//extract SOAPHeaders from the envelope and a them to the mimeHeaders
if(response.getSOAPHeader()!=null)
{
javax.xml.soap.SOAPHeader header = response.getSOAPHeader();
NodeList nodes = header.getChildNodes();
for(int x=0; x<nodes.getLength();x++)
{
//if the header entry contains child nodes - write them with the node names
if(nodes.item(x).hasChildNodes()){
NodeList childnodes = nodes.item(x).getChildNodes();
for(int y = 0; y<childnodes.getLength();y++){
responseBean.addEntryToResponseHeaders(nodes.item(x).getLocalName(),childnodes.item(y).getLocalName()+":"+childnodes.item(y).getTextContent());
}
}
else{
responseBean.addEntryToResponseHeaders(nodes.item(x).getLocalName(), nodes.item(x).getTextContent());
}
}
}
}
/*
* ???
*
* @param response
* @param responseBean
* @return
* @throws TransformerException
* @throws SOAPException
* @throws ParserConfigurationException
*/
private Document handleSoapResponse(SOAPMessage response, HttpResponseBean responseBean)
throws TransformerException, SOAPException,
ParserConfigurationException {
Node responseNode = null;
if (response!=null) {
responseNode = extractResponseNode(response);
extractHeaderDataSOAP(response, responseBean);
}
// build new xml document for assertion
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document newDocument = builder.newDocument();
Node adoptedBlob = newDocument.importNode(responseNode, true);
newDocument.appendChild(adoptedBlob);
// Output as String if required
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
ByteArrayOutputStream out = new ByteArrayOutputStream();
transformer.transform(new DOMSource(newDocument), new StreamResult(out));
if (logger.isDebugEnabled()) {
logger.debug("\n Return Doc \n");
logger.debug(new String(out.toByteArray()));
}
return newDocument;
}
public Node extractResponseNode(SOAPMessage response) throws SOAPException{
Node responseNode;
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
try {
response.writeTo(outStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
// logger.LogBetfairDebugEntry("SOAP Response: " + outStream.toString());
if (response.getSOAPBody().hasFault()) {
responseNode = response.getSOAPBody().getFault();
}
else if(response.getSOAPBody().getFirstChild() == null){ // Response type is void
responseNode = response.getSOAPBody();
}
else {
// extract the body
SOAPBody respBody = response.getSOAPBody();
// First child should be the service name object
Node serviceResponseNode = respBody.getFirstChild();
// second child
responseNode = serviceResponseNode.getFirstChild();
}
return responseNode;
}
/*
* Create and return a HttpMethodBase for a Rest request based on the passed
* HttpCallBean and CougarMessageProtocolRequestTypeEnum.
*
* @param httpCallBean
* @param protocolRequestType
* @return
*/
public HttpUriRequest getRestMethod(HttpCallBean httpCallBean, CougarMessageProtocolRequestTypeEnum protocolRequestType) {
Object postQueryObject = httpCallBean.getPostQueryObjectsByEnum(protocolRequestType);
String postQuery;
if (postQueryObject == null) {
postQuery = null;
} else {
postQuery = (String)postQueryObject;
}
String serviceExtension = httpCallBean.getServiceExtension();
String version = httpCallBean.getVersion();
Map<String, String> queryParams = httpCallBean.getQueryParams();
String host = httpCallBean.getHost();
String port = httpCallBean.getPort();
String path = httpCallBean.getPath();
String altURL = httpCallBean.getAlternativeURL(); // Will be "" for standard URL, or "/www" for alternative URL
boolean batchedQuery = httpCallBean.getJSONRPC();
String fullPath = httpCallBean.getFullPath();
String methodURL = "";
if(batchedQuery){ // If request is a batched JSON request set the URL to the appropriate baseline URL
postQuery = createBatchedPostString(httpCallBean.getBatchedRequests()); // Build the post string out of the list of requests to batch
methodURL = "http://" + host + ":" + port + "/json-rpc";
}
else{ // else build the request URL
String queryParamString = "";
if (queryParams != null) {
int counter = 0;
StringBuilder queryBuff = new StringBuilder();
for (Map.Entry<String,String> entry : queryParams.entrySet()) {
String value = entry.getValue();
String key = entry.getKey();
if (counter == 0) {
String firstQuery = "?" + key + "=" + value;
queryBuff.append(firstQuery);
} else {
String nextQuery = "&" + key + "=" + value;
queryBuff.append(nextQuery);
}
counter++;
}
queryParamString = queryBuff.toString();
}
if (fullPath != null) {
methodURL = "http://" + host + ":" + port + fullPath + queryParamString;
}
else {
methodURL = "http://" + host + ":" + port + altURL + "/" + serviceExtension + "/" + version + "/"
+ path + queryParamString;
}
}
// if (logger.isDebugEnabled()) {
// }
if ((postQuery != null) && (!postQuery.equalsIgnoreCase(""))) {
HttpPost method = new HttpPost(methodURL);
try {
method.setEntity(new StringEntity(postQuery,
null, UTF8));
return method;
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
} else {
return new HttpGet(methodURL);
}
}
private String createBatchedPostString(List<BatchedRequestBean> requests){
StringBuilder postQuery = new StringBuilder();
postQuery.append("[");
for(BatchedRequestBean entry : requests){ // build each request String and add to post string
//if version not set - default to "2.0", if service not set - default to "Baseline"
String version = entry.getVersion();
String service = entry.getService();
String method = entry.getMethod();
String params = entry.getParams();
String id = entry.getId();
postQuery.append("{ \"jsonrpc\": \"").append(version).append("\", \"method\": \"").append(service).append("/v")
.append(version).append("/").append(method).append("\", \"params\": ").append(params).append(", \"id\": ").append(id).append("}");
postQuery.append(",");
}
postQuery.deleteCharAt(postQuery.length()-1); // Remove last comma
postQuery.append("]");
return postQuery.toString();
}
/**
* Send a request to a locally running Cougar container via REST as per the
* passed parameters.
*/
public HttpResponseBean makeRestCougarHTTPCall(HttpCallBean httpCallBean, HttpUriRequest method, CougarMessageProtocolRequestTypeEnum protocolRequestType, CougarMessageContentTypeEnum responseContentTypeEnum, CougarMessageContentTypeEnum requestContentTypeEnum) {
Map<String, String> headerParams = httpCallBean.getHeaderParams();
String authority = httpCallBean.getAuthority();
Map <String, String> authCredentials = httpCallBean.getAuthCredentials();
Map<String, String> acceptProtocols = httpCallBean.getAcceptProtocols();
String ipAddress = httpCallBean.getIpAddress();
String altUrl = httpCallBean.getAlternativeURL();
Object postQueryObject = httpCallBean.getPostQueryObjectsByEnum(protocolRequestType);
String postQuery;
if (postQueryObject == null) {
postQuery = null;
} else {
postQuery = (String)postQueryObject;
}
InputStream inputStream = null;
try {
completeRestMethodBuild(method, responseContentTypeEnum, requestContentTypeEnum, postQuery, headerParams, authority, authCredentials,altUrl, acceptProtocols, ipAddress);
if (logger.isDebugEnabled()) {
logger.debug("Request");
logger.debug("=======");
logger.debug("URI: '" + method.getURI() + "'");
Header[] headers = method.getAllHeaders();
for (Header h : headers) {
logger.debug("Header: '"+h.getName()+" = "+h.getValue()+"'");
}
logger.debug("Body: '" + postQuery + "'");
}
Date requestTime = new Date();
final HttpResponse httpResponse = cougarDAO.executeHttpMethodBaseCall(method);
inputStream = httpResponse.getEntity().getContent();
String response = buildResponseString(inputStream);
if (logger.isDebugEnabled()) {
logger.debug("Response");
logger.debug("========");
logger.debug(String.valueOf(httpResponse.getStatusLine()));
Header[] headers = httpResponse.getAllHeaders();
for (Header h : headers) {
logger.debug("Header: '"+h.getName()+" = "+h.getValue()+"'");
}
logger.debug("Body: '" + response + "'");
}
Date responseTime = new Date();
return buildHttpResponseBean(httpResponse, response, requestTime, responseTime);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (inputStream!=null) {
try {
inputStream.close();
} catch (IOException e) { /*ignore*/}
}
}
}
private String buildResponseString(InputStream is) throws IOException{
List<Integer> bytes = new ArrayList<Integer>();
int read;
while((read = is.read()) != -1){
bytes.add(read);
}
byte[] buffer = new byte[bytes.size()];
for(int i = 0; i < bytes.size(); i++){
buffer[i] = bytes.get(i).byteValue();
}
return new String(buffer, "UTF-8");
}
public void setCougarDAO(ICougarDAO cougarDAO) {
this.cougarDAO = cougarDAO;
}
public static void main(String[] args) {
CougarHelpers ch = new CougarHelpers();
ch.setJMXConnectionFactory();
}
/*
* Find the VM instance running Cougar based on COUGARVMNAME1 and COUGARVMNAME2
* fields, and attach, setting the JmxConnector to be used by other methods.
*
*/
private void setJMXConnectionFactory() {
String id = null;
List<VirtualMachineDescriptor> vms = VirtualMachine.list();
Boolean foundVM = false;
for (VirtualMachineDescriptor vmd : vms) {
String vmName = cleanCommandLineArgs(vmd.displayName());
id = vmd.id();
JMXConnector jmxConnector = null;
try{
jmxConnector = createJMXConnector(id);
}
catch(Exception e){//Do Nothing move onto next vm
continue;
}
try{
if (!makeServerConnection(jmxConnector)) {
continue;
}
}
catch(Exception e){//Do Nothing move onto next vm
continue;
}
//No exceptions thrown so we have our cougar vm
jmxc = jmxConnector;
foundVM = true;
break;
}
if (!foundVM) {
throw new RuntimeException("Unable to find cougar VM");
}
}
/*
* Clean any command line args from a vm display name before comparing it with expected values
*/
private String cleanCommandLineArgs(String vmName){
vmName = vmName.replaceAll("\"", ""); // Strip any quotes from the name (needed for running on Jenkins server)
StringBuffer buff = new StringBuffer(vmName);
int argIndex = -1;
while((argIndex = buff.indexOf("-D")) != -1){ // While there's a command line argument in the string
int argEnd = -1;
if((argEnd = buff.indexOf(" ", argIndex)) == -1){ // If this argument is at the end of the display name then clean to the end rather than to next white space
argEnd = buff.length();
}
buff.replace(argIndex-1, argEnd, ""); // remove contents of buffer between space before arg starts and the next white space/end of buffer
}
return buff.toString();
}
public JMXConnector createJMXConnector(String id) throws IOException,AgentLoadException,
AgentInitializationException, AttachNotSupportedException {
// attach to the target application
VirtualMachine vm = VirtualMachine.attach(id);
// get the connector address
String connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
// no connector address, so we start the JMX agent
if (connectorAddress == null) {
String agent = vm.getSystemProperties()
.getProperty("java.home")
+ File.separator
+ "lib"
+ File.separator
+ "management-agent.jar";
vm.loadAgent(agent);
// agent is started, get the connector address
connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
}
// establish connection to connector server
JMXServiceURL url = new JMXServiceURL(connectorAddress);
return JMXConnectorFactory.connect(url);
}
public boolean makeServerConnection(JMXConnector jmxConnector) throws IOException, MBeanException,
AttributeNotFoundException, InstanceNotFoundException, ReflectionException, MalformedObjectNameException{
MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();
Set<ObjectName> mbeans = mBeanServerConnection.queryNames(new ObjectName("CoUGAR:name=healthChecker,*"), null);
if (!mbeans.isEmpty()) {
mBeanServerConnection.getAttribute(mbeans.iterator().next(), "SystemInService");
return true;
}
return false;
}
/*
* Produce an alphabetically ordered array of the method names of a given class
*/
private String[] getOrderedMethodNamesFromClass(String classPath) throws ClassNotFoundException{
Class baseline = Class.forName(classPath);
Method[] methods = baseline.getDeclaredMethods();
String[] methodNames = new String[methods.length];
for(int i = 0; i < methods.length; i++){
methodNames[i] = methods[i].getName();
}
Arrays.sort(methodNames);
return methodNames;
}
/*
* Get the path of a given operation (either from the map of paths or itself)
*/
private String getPath(String name){
if(OPERATION_PATHS.containsKey(name)){ // If operation path is different to name then get it
return OPERATION_PATHS.get(name);
}
return name; // Else return original name
}
private MBeanServerConnection getJMXConnection() {
try {
if (jmxc == null) {
setJMXConnectionFactory();
}
return jmxc.getMBeanServerConnection();
} catch (IOException e) {
throw new RuntimeException("Problem connecting to cougar JMX", e);
}
}
private void setJMXMBeanAttribute(String mBeanName, String attributeName,
Object newMbeanValue) {
try {
MBeanServerConnection mBeanServerConnection = getJMXConnection();
ObjectName mbeanName = new ObjectName(mBeanName);
Object currentAttributeValue = mBeanServerConnection.getAttribute(mbeanName, attributeName);
Object reflectedValue = reflect.getRealProperty(currentAttributeValue.getClass(), newMbeanValue);
Attribute attribute = new Attribute(attributeName, reflectedValue);
mBeanServerConnection.setAttribute(mbeanName, attribute);
} catch (Exception e) {
throw new RuntimeException(JMX_SETTING_ERROR + mBeanName + ": " + attributeName, e);
}
}
public void setJMXFaultControllerAttribute(String attributeName,
String value) {
String mBeanName = "CoUGAR:name=faultController";
setJMXMBeanAttribute(mBeanName, attributeName, value);
}
private HttpResponseBean buildHttpResponseBean(HttpResponse httpResponse, String response, Date requestTime, Date responseTime) {
HttpResponseBean httpResponseBean = new HttpResponseBean();
Header[] headersArray = httpResponse.getAllHeaders();
Map<String, String[]> headersMap = new HashMap<>();
for (Header header: headersArray) {
String[] headerAttributes = header.toString().split(": ");
headersMap.put(headerAttributes[0], new String[] { headerAttributes[1].replace("\r\n", "")});
}
httpResponseBean.setResponseHeaders(headersMap);
httpResponseBean.setHttpStatusCode(httpResponse.getStatusLine().getStatusCode());
httpResponseBean.setHttpStatusText(httpResponse.getStatusLine().getReasonPhrase());
httpResponseBean.setRequestTime(new Timestamp(requestTime.getTime()));
httpResponseBean.setResponseTime(new Timestamp(responseTime.getTime()));
if ((response != null) && (!response.equalsIgnoreCase(""))) {
httpResponseBean.setResponseObject(response);
} else {
httpResponseBean.setResponseObject(null);
}
return httpResponseBean;
}
private void completeRestMethodBuild(HttpUriRequest method,
CougarMessageContentTypeEnum responseContentTypeEnum,
CougarMessageContentTypeEnum requestContentTypeEnum,
String postQuery, Map<String, String> headerParams,
String authority, Map <String, String> authCredentials, String altUrl,
Map<String, String> acceptProtocols, String ipAddress) {
String contentType = selectContent(requestContentTypeEnum);
if(!"".equals(contentType)){
method.setHeader("Content-Type", contentType);
}
method.setHeader("User-Agent", "java/socket");
String accept = selectAccept(responseContentTypeEnum, acceptProtocols);
method.setHeader("Accept", accept);
// No need to set this header any more as it is set by the new http client version
/*if ((postQuery != null) && (!postQuery.equalsIgnoreCase(""))) {
Integer contentLength = postQuery.length();
method.setHeader("Content-Length", contentLength.toString());
}*/
if (headerParams != null) {
for (Map.Entry<String, String>entry : headerParams.entrySet()) {
String headerParamValue = entry.getValue();
String key = entry.getKey();
method.setHeader(key, headerParamValue);
// logger.LogBetfairDebugEntry("Rest request header param added: '"
// + key + ":" + headerParamValue + "'");
}
}
if (authority != null) {
method.setHeader("X-Authentication", authority);
}
if (authCredentials != null) {
if("".equals(altUrl)){
method.setHeader("X-Token-Username", authCredentials.get("Username"));
method.setHeader("X-Token-Password", authCredentials.get("Password"));
}
else{
method.setHeader("X-AltToken-Username", authCredentials.get("Username"));
method.setHeader("X-AltToken-Password", authCredentials.get("Password"));
}
}
if (ipAddress==null) {
method.setHeader("X-Forwarded-For", null);
} else if (!ipAddress.trim().equalsIgnoreCase("DO NOT INCLUDE")) {
method.setHeader("X-Forwarded-For", ipAddress);
}
//logger.LogBetfairDebugEntry("Rest request postString: '"
// + postQuery + "'");
}
private String selectContent(CougarMessageContentTypeEnum requestContentTypeEnum){
switch (requestContentTypeEnum) {
case JSON:
// logger.LogBetfairDebugEntry("Rest request Content-Type: "+ JSON_CONTENT);
return JSON_CONTENT;
case XML:
// logger.LogBetfairDebugEntry("Rest request Content-Type: "+ XML_CONTENT);
return XML_CONTENT;
case OTHER:
//DO NOTHING
return "";
default:
throw new RuntimeException(
"Unsupported request message content type supplied: "
+ requestContentTypeEnum.toString());
}
}
private String selectAccept(CougarMessageContentTypeEnum responseContentTypeEnum,Map<String,String> acceptProtocols){
if (responseContentTypeEnum == null) {
int loopCounter = 0;
StringBuffer acceptBuff = new StringBuffer();
for (Map.Entry<String,String> entry : acceptProtocols.entrySet()) {
String ranking = entry.getValue();
String protocol = entry.getKey();
if (loopCounter == 0) {
if ((ranking != null) && (!ranking.equalsIgnoreCase(""))) {
String firstProtocolWithRanking = protocol + ";" + ranking;
acceptBuff.append(firstProtocolWithRanking);
} else {
acceptBuff.append(protocol);
}
} else {
String nextProtocolWithRanking = "," + protocol + ";" + ranking;
acceptBuff.append(nextProtocolWithRanking);
// logger.LogBetfairDebugEntry("Rest request Accept protocol: "+acceptBuff.toString());
}
loopCounter++;
}
return acceptBuff.toString();
} else {
switch (responseContentTypeEnum) {
case JSON:
// logger.LogBetfairDebugEntry("Rest request Accept protocol: "
// + JSON_CONTENT);
return JSON_CONTENT;
case XML:
// logger.LogBetfairDebugEntry("Rest request Accept protocol: "
// + XML_CONTENT);
return XML_CONTENT;
default:
throw new RuntimeException(
"Unsupported response message content type supplied: "
+ responseContentTypeEnum.toString());
}
}
}
public void setJMXMBeanAttributeValue(String mBeanName, String attributeName, Object value) {
try {
MBeanServerConnection mBeanServerConnection = getJMXConnection();
ObjectName mbeanName = new ObjectName(mBeanName);
Attribute attr = new Attribute(attributeName, value);
mBeanServerConnection.setAttribute(mbeanName, attr);
} catch (Exception e) {
throw new RuntimeException(JMX_RETRIEVAL_ERROR + mBeanName + ": " + attributeName, e);
}
}
public void setSOAPSchemaValidationEnabled(boolean validationEnabled) {
setJMXMBeanAttributeValue("com.betfair.cougar.transport:type=soapCommandProcessor", "SchemaValidationEnabled", validationEnabled);
}
private Object getJMXMBeanAttributeValue(String mBeanName, String attributeName) {
try {
MBeanServerConnection mBeanServerConnection = getJMXConnection();
ObjectName mbeanName = new ObjectName(mBeanName);
return mBeanServerConnection.getAttribute(mbeanName, attributeName);
} catch (Exception e) {
throw new RuntimeException(JMX_RETRIEVAL_ERROR + mBeanName + ": " + attributeName, e);
}
}
private Object invokeJMXMBeanOperation(String mBeanName, String operationName, Object[] params,
String[] signature) {
try {
MBeanServerConnection mBeanServerConnection = getJMXConnection();
return mBeanServerConnection.invoke(new ObjectName(mBeanName), operationName, params, signature);
} catch (Exception e) {
throw new RuntimeException(JMX_INVOKE_ERROR + mBeanName + ": " + operationName +
" with arguments : " + Arrays.toString(params), e);
}
}
public String getJMXLoggingManagerAttributeValue(String attributeName) {
String mBeanName = "CoUGAR:name=Logging";
return getJMXMBeanAttributeValue(mBeanName, attributeName).toString();
}
public String getJMXApplicationPropertyValue(String key) {
String mBeanName = "CoUGAR:name=ApplicationProperties";
return (String) invokeJMXMBeanOperation(mBeanName, "getProperty",
new Object[]{key},
new String[]{"java.lang.String"});
}
public String getJMXSystemPropertyValue(String propertyName)
{
TabularData sysProps = (TabularData) getJMXMBeanAttributeValue("java.lang:type=Runtime", "SystemProperties");
return (String) sysProps.get(new String[]{"user.dir"}).get("value");
}
public String getRuntimeAttributeValue(String attributeName){
String mBeanName = "java.lang:type=Runtime";
return getJMXMBeanAttributeValue(mBeanName, attributeName).toString();
}
public String getJMXAttributeValue(String mBeanName, String attributeName){
return getJMXMBeanAttributeValue(mBeanName, attributeName).toString();
}
/**
* Returns the system Java version string in the format usable for User-Agent field
* in cougar log
* @return String
*/
public String getJavaVersion() {
String s = "";
Pattern myPattern = Pattern.compile("(.*?)\\-");
Matcher m = myPattern.matcher(System.getProperty("java.runtime.version"));
while (m.find()) {
s = m.group(1);
}
return "\"Java/" + s + "\"";
}
public Map<String,String> convertFaultObjectToMap(HttpResponseBean soapResp){
DocumentImpl doc = (DocumentImpl) soapResp.getResponseObject();
String actualFaultCode = doc.getElementsByTagName("faultcode").item(0).getFirstChild().getNodeValue();
String actualFaultString = doc.getElementsByTagName("faultstring").item(0).getFirstChild().getNodeValue();
String actualMessage = doc.getElementsByTagName("message").item(0).getFirstChild().getNodeValue();
Node actualTraceNode = doc.getElementsByTagName("trace").item(0).getFirstChild();
String actualTrace = "";
if (actualTraceNode != null) {
actualTrace = actualTraceNode.getNodeValue();
actualTrace = actualTrace.replace("\r", ""); // Clean string of escaped characters (to avoid errors on Linux CI build)
actualTrace = actualTrace.trim();
}
Map<String,String> responseMap = new HashMap<String, String>();
responseMap.put("faultCode", actualFaultCode);
responseMap.put("faultString", actualFaultString);
responseMap.put("faultMessage", actualMessage);
responseMap.put("faultTrace", actualTrace);
return responseMap;
}
// Method to convert batched JSON response to a map for comparison (as the order of the array of responses cannot be relied upon)
public Map<String,Object> convertBatchedResponseToMap(HttpResponseBean batchedResponse) throws JSONException{
JSONObject json = (JSONObject) batchedResponse.getResponseObject();
JSONArray results = null;
try {
results = (JSONArray) json.get("response");
}
catch (JSONException je) {
logger.debug(String.valueOf(json),je);
throw je;
}
Map<String, Object> responseMap = new HashMap<String, Object >();
for(int i = 0; i < results.length(); i++){
JSONObject jsonObject = results.getJSONObject(i);
responseMap.put("response"+ jsonObject.get("id"), jsonObject.toString());
}
responseMap.put("httpStatusCode",batchedResponse.getHttpStatusCode()+"");
responseMap.put("httpStatusText",batchedResponse.getHttpStatusText());
responseMap.put("requestTime", batchedResponse.getRequestTime());
responseMap.put("responseTime", batchedResponse.getResponseTime());
return responseMap;
}
public Date convertToSystemTimeZone(String datetoconvert)
{
TimeZone tz = TimeZone.getDefault();
Date date = new Date();
try{
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
String s = datetoconvert;
String[] tmp = s.split(".0Z");
String s1= tmp[0];
logger.debug("given string is" +s1);
date = dateFormat.parse(s1);
logger.debug("OffsetValue is " +tz.getRawOffset());
if(tz.getRawOffset()!= 0)
date = new Date(date.getTime() + tz.getRawOffset());
logger.debug("After adding offset" +date);
if ( tz.inDaylightTime( date ))
{
Date dstDate = new Date( date.getTime() + tz.getDSTSavings() );
logger.debug("Day Light Saving is "+ tz.getDSTSavings());
logger.debug("Dst is "+ dstDate);
if ( tz.inDaylightTime( dstDate ))
{
date = dstDate;
// logger.debug("dst date "+ dstDate);
}
}
logger.debug("After the day light saving" +date);
}
catch(Exception e)
{
logger.debug("System exception caught" +e);
}
return date;
}
public String dateInUTC(Date date) {
if (date == null) {
return "null";
}
return date.toGMTString().replace("GMT","UTC");
}
}